import { ForbiddenException, Injectable } from '@nestjs/common';
import { CreateStudentDto } from './dto/create-student.dto';
import { UpdateStudentDto } from './dto/update-student.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Student } from './entities/student.entity';
import { Repository } from 'typeorm';
import { GetStudentDto, ReturnStudentDtoList } from './dto/get-student.dto';
import { conditionUtilsLike } from '../utils/db.help';
import { encrypt } from '../utils/crypto';
import { RolesService } from '../roles/roles.service';
import { Menu } from '../menus/entities/menu.entity';
import { menuTree } from '../utils';

@Injectable()
export class StudentService {
  constructor(
    private readonly rolesService: RolesService,
    @InjectRepository(Student) private studentRepository: Repository<Student>,
  ) {}

  // 创建学生
  async create(createStudentDto: CreateStudentDto) {
    const student = await this.findOne(createStudentDto.studentNumber);
    if (student) {
      throw new ForbiddenException('学号重复');
    }
    const list = await this.rolesService.returnRolesServiceEntities(
      createStudentDto.roleIds,
    );
    createStudentDto.roles = list;
    // 加密
    createStudentDto.password = encrypt(
      createStudentDto.password ? createStudentDto.password : '123456',
    );
    const res = await this.studentRepository.create(createStudentDto);
    return await this.studentRepository.save(res);
  }

  // 根据学号查询
  findOne(studentNumber: string) {
    return this.studentRepository.findOne({ where: { studentNumber } });
  }

  // 学生搜索
  async findAll(query: GetStudentDto) {
    const { page, limit, name, studentNumber, blur } = query;
    const conditions = [
      { field: 's_name', value: name },
      { field: 'studentNumber', value: studentNumber },
    ];
    const queryBuilder = await this.studentRepository.createQueryBuilder(
      'student',
    );
    const newQueryBuilder = conditionUtilsLike<Student>(
      queryBuilder,
      conditions,
      'student',
    );
    if (blur) {
      newQueryBuilder.andWhere(
        '(student.s_name LIKE :searchQuery OR student.studentNumber LIKE :searchQuery OR student.s_address LIKE :searchQuery)',
        {
          searchQuery: `%${blur}%`,
        },
      );
    }
    const count = await newQueryBuilder.getCount();
    const content = await newQueryBuilder
      .leftJoinAndSelect('student.major', 'major')
      .leftJoinAndSelect('student.department', 'department')
      .leftJoinAndSelect('student.classInfo', 'classInfo')
      .skip((page - 1) * limit || 0)
      .take(limit || 10)
      .getMany();
    return {
      content,
      totalElements: count,
      totalPages: Number(page || 1),
    } as unknown as ReturnStudentDtoList;
  }

  // 查询学生详情
  async findUserDetail(sid: string) {
    const res = await this.studentRepository
      .createQueryBuilder('student')
      .leftJoinAndMapMany('student.roles', 'student.roles', 'role')
      .leftJoinAndMapMany('role.menus', 'role.menus', 'menus')
      .andWhere('student.sid = :sid', { sid })
      .getOne();
    const menus: Menu[] = [];
    res.roles.map((item) => {
      if (item.menus.length) {
        menus.push(...item.menus);
      }
    });
    // 角色
    const roles: { id: number; name: string }[] = res.roles.map((item) => {
      return {
        id: item.id,
        name: item.name,
      };
    });
    // 按钮权限
    const buttonList: string[] = [];
    menus.map((item) => {
      if (item.node_type === 3) {
        buttonList.push(item.menu_code);
      }
    });
    // 菜单列表
    // let menusList: any = [];
    // menusList = menuTree(menus, 0);
    return {
      userInForm: await this.findDetail(sid),
      roles,
      buttonList,
      // menusList,
    };
  }

  async findDetail(sid: string) {
    return this.studentRepository.findOne({
      relations: ['department', 'major'],
      where: { sid },
    });
  }

  // 更新学生
  async update(sid: string, updateStudentDto: UpdateStudentDto) {
    const res = await this.findDetail(sid);
    if (!res?.sid) {
      throw new ForbiddenException('学生不存在！');
    }
    // 加密
    // updateStudentDto.password = encrypt(updateStudentDto.password);
    delete res.major;
    delete res.department;
    const newStudent = this.studentRepository.merge(res, updateStudentDto);
    return await this.studentRepository.save(newStudent);
  }

  // 删除
  async remove(id: string) {
    const res = await this.findDetail(id);
    if (res?.sid) {
      return await this.studentRepository.remove(res);
    }
    throw new ForbiddenException('学生不存在！');
  }

  // 根据账号密码查询学生
  async loginStudent(s_name: string, password: string) {
    return this.studentRepository.findOne({
      relations: ['roles'],
      where: { s_name, password },
    });
  }
}
